package med.movyzer.core;
import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

import med.movyzer.datastructs.Logger;
import med.movyzer.datastructs.MovementSeries;
import med.movyzer.gui.MovyzerFileChooser;
import med.movyzer.gui.MovyzerPlot;
import med.movyzer.io.GT3XData;
import med.movyzer.io.MovyzerDataInterface;
import med.movyzer.io.PSGData;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.TimeSeries;

@SuppressWarnings("serial")
public class MovyzerMain extends JFrame{

	//These are the start position values of the main frame
	static int x = 25;
	static int y = 25;
	private File fileChooserChoosenFile;
	private int fileChooserDialogResult;

	static int instance = 0;
	ChartPanel chartPanel;
	MovyzerPlot plot=new MovyzerPlot();
	JTextField leftGravity;
	JTextField leftTreshold;
	JTextField leftTresholdLM;
	JTextField leftTresholdTM;
	JTextField rightGravity;
	JTextField rightTreshold;
	JTextField rightTresholdLM;
	JTextField rightTresholdTM;
	JTextField psgTresholdLM;
	JTextArea log;
	JTextArea gt3xInfo;
	JTextArea psgInfo;
	MovyzerDataInterface gt3xDataLeft;
	MovyzerDataInterface gt3xDataRight;
	MovyzerDataInterface psgData;
	MovementSeries gt3xLMsLeft;
	MovementSeries gt3xPLMsLeft;
	MovementSeries gt3xLMsRight;
	MovementSeries gt3xPLMsRight;
	MovementSeries psgLMs;
	MovementSeries psgPLMs;
	String gt3xFileNameLeft=null;
	String gt3xFileNameRight=null;
	String psgFileName=null;
	SimilarityView simView=null;

	public MovyzerMain(int x, int y, int instance) {
		this.getContentPane().setLayout(null);
		this.initWindow();
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		this.setTitle("Movyzer"+" (Instance "+instance+")");
		this.setLocation(x, y);
		try {
			Image img = ImageIO.read(this.getClass().getResource("/med/movyzer/gui/gfx/movyzer_mainframe-icon.png"));
			this.setIconImage(img);
		} catch (Exception e) {
		} 

		this.setVisible(true);
	}	

	protected void initWindow() 
	{
		JMenuBar menuBar = new JMenuBar();
		this.setJMenuBar(menuBar);

		JMenu menu1 = new JMenu("File");
		menuBar.add(menu1);

		JMenu menu2 = new JMenu("Options");
		menuBar.add(menu2);

		JMenu menu3 = new JMenu("Help");
		menuBar.add(menu3);
		
		JMenuItem fileMenuItem1 = new JMenuItem("Open GT3X-File (Left Side)");
		fileMenuItem1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				FileFilter filter = new FileNameExtensionFilter("GT3X file", "csv", "gt3x");
				MovyzerFileChooser c = new MovyzerFileChooser(MovyzerFileChooser.GT3X);
				c.setDialogTitle("Select GT3X Sensor file (Left Side)");
				c.addChoosableFileFilter(filter);
				c.setVisible(true);
				fileChooserDialogResult = c.showOpenDialog(null);
				if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
					fileChooserChoosenFile = c.getSelectedFile();
				}
				openGT3XFileLeft();				
			}
		});
		menu1.add(fileMenuItem1);
		
		JMenuItem fileMenuItem0 = new JMenuItem("Open GT3X-File (Right Side)");
		fileMenuItem0.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				FileFilter filter = new FileNameExtensionFilter("GT3X file", "csv", "gt3x");
				MovyzerFileChooser c = new MovyzerFileChooser(MovyzerFileChooser.GT3X);
				c.setDialogTitle("Select GT3X Sensor file (Right Side)");
				c.addChoosableFileFilter(filter);
				c.setVisible(true);
				fileChooserDialogResult = c.showOpenDialog(null);
				if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
					fileChooserChoosenFile = c.getSelectedFile();
				}
				openGT3XFileRight();				
			}
		});
		menu1.add(fileMenuItem0);
		

		JMenuItem fileMenuItem2 = new JMenuItem("Open PSG-File");
		fileMenuItem2.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				FileFilter filter = new FileNameExtensionFilter("PSG file", "csv", "psg");
				MovyzerFileChooser c = new MovyzerFileChooser(MovyzerFileChooser.PSG);
				c.setDialogTitle("Select PSG Sensor file");
				c.addChoosableFileFilter(filter);
				c.setVisible(true);
				fileChooserDialogResult = c.showOpenDialog(null);
				if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
					fileChooserChoosenFile = c.getSelectedFile();
				}
				openPSGFile();				
			}
		});
		menu1.add(fileMenuItem2);
		
		JMenuItem fileMenuItem3 = new JMenuItem("Export GT3X-File (Left Side)");
		fileMenuItem3.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				exportLeft();
			}
		});
		menu1.add(fileMenuItem3);
		
		JMenuItem fileMenuItem4 = new JMenuItem("Export GT3X-File (Right Side)");
		fileMenuItem4.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				exportRight();
			}
		});
		menu1.add(fileMenuItem4);


		JMenuItem optionsMenuItem0 = new JMenuItem("New Main");
		optionsMenuItem0.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				// Move every new Window (for better Handling), but not further than 250 px 
				if (x<250 && y<250){
					x += 25;
					y += 25;
				}
				instance++;
				new MovyzerMain(x, y, instance);				
			}
		});
		menu2.add(optionsMenuItem0);

		JMenuItem optionsMenuItem1 = new JMenuItem("Similarity (Left)");
		optionsMenuItem1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				openSimilarityViewLeft();
			}
		});
		menu2.add(optionsMenuItem1);
		
		JMenuItem optionsMenuItem2 = new JMenuItem("Similarity (Right)");
		optionsMenuItem2.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				openSimilarityViewRight();
			}
		});
		menu2.add(optionsMenuItem2);

		JMenuItem helpMenuItem0 = new JMenuItem("Web");
		helpMenuItem0.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				web();				
			}
		});
		menu3.add(helpMenuItem0);

		JMenuItem helpMenuItem1 = new JMenuItem("About");
		helpMenuItem1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				about();				
			}
		});
		menu3.add(helpMenuItem1);

		// Init Welcome Screen
		chartPanel = new ChartPanel(null);
		chartPanel.setBounds(5, 5, 880, 600);
		((Component) chartPanel).setBackground(Color.decode("0x000000"));

		XYPlot p = new XYPlot();

		try {
			Image img = ImageIO.read(this.getClass().getResource("/med/movyzer/gui/gfx/movyzer_bkg.png"));
			p.setBackgroundImage(img);
		} catch (Exception e) {
		} 
		JFreeChart chart=new JFreeChart("",p);
		chartPanel.setChart(chart);
		add(chartPanel);
		
		JLabel leftGravityLabel=new JLabel("Earth Gravity");
		leftGravityLabel.setBounds(900, 10, 100, 20);
		add(leftGravityLabel);
		leftGravity=new JTextField("9810");
		leftGravity.setBounds(900, 30, 100, 20);
		add(leftGravity);
		JLabel leftTresholdLabel=new JLabel("Threshold (gravity)");
		leftTresholdLabel.setBounds(900, 50, 150, 20);
		add(leftTresholdLabel);
		leftTreshold=new JTextField("100");
		leftTreshold.setBounds(900, 70, 100, 20);
		add(leftTreshold);
		JLabel leftTresholdLMLabel=new JLabel("Threshold (LMs)");
		leftTresholdLMLabel.setBounds(900, 90, 100, 20);
		add(leftTresholdLMLabel);
		leftTresholdLM=new JTextField("1.0");
		leftTresholdLM.setBounds(900, 110, 100, 20);
		add(leftTresholdLM);
		JLabel timeFrameThresholdLabel=new JLabel("Threshold (TF)");
		timeFrameThresholdLabel.setBounds(900, 130, 100, 20);
		add(timeFrameThresholdLabel);
		leftTresholdTM=new JTextField(String.valueOf(GT3XData.MOVEMENT_TIME_SHIFT_THRESHOLD));
		leftTresholdTM.setBounds(900, 150, 100, 20);
		add(leftTresholdTM);
		JButton applyLeft=new JButton("apply");
		applyLeft.setBounds(900,170,100,20);
		applyLeft.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(gt3xDataLeft!=null){
					applyParametersLeft();
					updateLeft();
				}
			}
		});
		add(applyLeft);
		
		
		JLabel rightGravityLabel=new JLabel("Earth Gravity");
		rightGravityLabel.setBounds(900, 200, 100, 20);
		add(rightGravityLabel);
		rightGravity=new JTextField("9810");
		rightGravity.setBounds(900, 220, 100, 20);
		add(rightGravity);
		JLabel rightTresholdLabel=new JLabel("Threshold (gravity)");
		rightTresholdLabel.setBounds(900, 240, 150, 20);
		add(rightTresholdLabel);
		rightTreshold=new JTextField("100");
		rightTreshold.setBounds(900, 260, 100, 20);
		add(rightTreshold);
		JLabel rightTresholdLMLabel=new JLabel("Threshold (LMs)");
		rightTresholdLMLabel.setBounds(900, 280, 100, 20);
		add(rightTresholdLMLabel);
		rightTresholdLM=new JTextField("1.0");
		rightTresholdLM.setBounds(900, 300, 100, 20);
		add(rightTresholdLM);
		JLabel leftFrameThresholdLabel=new JLabel("Threshold (TF)");
		leftFrameThresholdLabel.setBounds(900, 320, 100, 20);
		add(leftFrameThresholdLabel);
		rightTresholdTM=new JTextField(String.valueOf(GT3XData.MOVEMENT_TIME_SHIFT_THRESHOLD));
		rightTresholdTM.setBounds(900, 340, 100, 20);
		add(rightTresholdTM);
		JButton applyRight=new JButton("apply");
		applyRight.setBounds(900,360,100,20);
		applyRight.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(gt3xDataRight!=null){
					applyParametersRight();
					updateRight();
				}
			}
		});
		add(applyRight);
		
		JLabel psgTresholdLMLabel=new JLabel("Threshold (LM)");
		psgTresholdLMLabel.setBounds(900, 400, 100, 20);
		add(psgTresholdLMLabel);
		psgTresholdLM=new JTextField("1.0");
		psgTresholdLM.setBounds(900, 420, 100, 20);
		add(psgTresholdLM);
		JButton applyPSG=new JButton("apply");
		applyPSG.setBounds(900,450,100,20);
		applyPSG.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(psgData!=null){
					updatePSG();
				}
			}
		});
		add(applyPSG);

		log=new JTextArea();
		JScrollPane scrollPane = new JScrollPane(log);
		scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane.setBounds(5, 620, 1000, 100);
		add(scrollPane);

		this.setBounds(0, 0, 1040, 800);
		this.getContentPane().setBackground(Color.decode("0xEEEEEE"));

	}

	private void openGT3XFileLeft(){
		if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
			gt3xDataLeft=new GT3XData();
			if(gt3xDataLeft.loadFile(fileChooserChoosenFile.getPath(),this)==false){
				return;
			}
			gt3xFileNameLeft=fileChooserChoosenFile.getName();
			Logger.print(log);

			updateLeft();
			//gt3xInfo.setText(gt3xData.getDescription());
		}

		calcSimilarityLeft();

		Logger.print(log);	
	}
	
	private void openGT3XFileRight(){
		if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
			gt3xDataRight=new GT3XData();
			if(gt3xDataRight.loadFile(fileChooserChoosenFile.getPath(),this)==false){
				return;
			}
			gt3xFileNameRight=fileChooserChoosenFile.getName();
			Logger.print(log);

			updateRight();

			//gt3xInfo.setText(gt3xData.getDescription());
		}

		calcSimilarityRight();

		Logger.print(log);	
	}

	private void openPSGFile(){
		if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
			psgData = new PSGData();
			if(psgData.loadFile(fileChooserChoosenFile.getPath(),this)==false){
				return;
			}
			Logger.print(log);

			updatePSG();
			
			if(gt3xDataLeft!=null){
				updateLeft();
			}
			if(gt3xDataRight!=null){
				updateRight();
			}
		}
		showTitle();
		calcSimilarityLeft();
		calcSimilarityRight();

		Logger.print(log);	
	}
	
	private void updateLeft(){
		if(psgData!=null){
			gt3xDataLeft.setEndShowTime(psgData.getEndTime());
		}
		
		TimeSeries lmSeries=gt3xDataLeft.getTimeSeries();
		lmSeries.setKey("LM-Movement");
		gt3xLMsLeft=gt3xDataLeft.getMovementSeries(Integer.parseInt(leftTresholdTM.getText())).getLMSeries(Double.parseDouble(leftTresholdLM.getText()));
		gt3xPLMsLeft=gt3xLMsLeft.getPLMSeries();
		TimeSeries plmSeries=gt3xPLMsLeft.getTimeSeries(1);
		plmSeries.setKey("PLM-Movement");
	
		plot.setGT3XDataLeft(lmSeries, plmSeries,gt3xLMsLeft.getTimeSeries(1));
	
		JFreeChart chart=new JFreeChart(plot);
		chartPanel.setChart(chart);
		chartPanel.setRangeZoomable(false);	
		
		if(gt3xDataLeft.isMobileFile() || gt3xDataLeft.isRawFile()){
			leftGravity.setEnabled(true);
			leftTreshold.setEnabled(true);
		}else{
			leftGravity.setEnabled(false);
			leftTreshold.setEnabled(false);			
		}
		showTitle();

		Logger.addEntry("Analyzing (Left): "+gt3xLMsLeft.size()+" LM found");
		Logger.addEntry("Analyzing (Left): "+gt3xPLMsLeft.size()+" PLM found");
		Logger.print(log);
	}
	
	private void updateRight(){
		if(psgData!=null){
			gt3xDataRight.setEndShowTime(psgData.getEndTime());
		}
		
		TimeSeries lmSeries=gt3xDataRight.getTimeSeries();
		lmSeries.setKey("LM-Movement");
		gt3xLMsRight=gt3xDataRight.getMovementSeries(Integer.parseInt(rightTresholdTM.getText())).getLMSeries(Double.parseDouble(leftTresholdLM.getText()));
		gt3xPLMsRight=gt3xLMsRight.getPLMSeries();
		TimeSeries plmSeries=gt3xPLMsRight.getTimeSeries(1);
		plmSeries.setKey("PLM-Movement");
	
		plot.setGT3XDataRight(lmSeries, plmSeries,gt3xLMsRight.getTimeSeries(1));
	
		JFreeChart chart=new JFreeChart(plot);
		chartPanel.setChart(chart);
		chartPanel.setRangeZoomable(false);	
		
		if(gt3xDataRight.isMobileFile() || gt3xDataRight.isRawFile()){
			rightGravity.setEnabled(true);
			rightTreshold.setEnabled(true);
		}else{
			rightGravity.setEnabled(false);
			rightTreshold.setEnabled(false);			
		}
		showTitle();
		Logger.addEntry("Analyzing (Right): "+gt3xLMsRight.size()+" LM found");
		Logger.addEntry("Analyzing (Right): "+gt3xPLMsRight.size()+" PLM found");
		Logger.print(log);
	}
	
	private void updatePSG(){		
		TimeSeries lmSeries=psgData.getTimeSeries();
		lmSeries.setKey("LM-Movement");
		psgLMs=psgData.getMData().getLMSeries(Double.parseDouble(psgTresholdLM.getText()));
		psgPLMs=psgLMs.getPLMSeries();
		TimeSeries plmSeries=psgPLMs.getTimeSeries(1);
		plmSeries.setKey("PLM-Movement");

		plot.setPSGData(lmSeries, plmSeries,psgLMs.getTimeSeries(1));

		psgFileName=fileChooserChoosenFile.getName();
		JFreeChart chart=new JFreeChart(plot);
		chartPanel.setChart(chart);
		chartPanel.setRangeZoomable(false);
		
		Logger.addEntry("Analyzing (PSG): "+psgLMs.size()+" LM found");
		Logger.addEntry("Analyzing (PSG): "+psgPLMs.size()+" PLM found");
		Logger.print(log);
	}

	private void applyParametersLeft(){
		gt3xDataLeft.setEarthGravity(Integer.parseInt(leftGravity.getText()));
		gt3xDataLeft.setTreshold(Integer.parseInt(leftTreshold.getText()));
	}
	
	private void applyParametersRight(){
		gt3xDataRight.setEarthGravity(Integer.parseInt(rightGravity.getText()));
		gt3xDataRight.setTreshold(Integer.parseInt(rightTreshold.getText()));
	}

	public void setTimeShiftLeft(int milliseconds){
		if(gt3xDataLeft!=null){
			gt3xDataLeft.setShift(gt3xDataLeft.getShift()+milliseconds);

			updateLeft();

			Logger.addEntry("Left GT3X data shifted: "+milliseconds +" ms");
			calcSimilarityLeft();
			simView.setGt3xSeries(gt3xLMsLeft);
			try {
				simView.calcSimilarity();
			} catch (Exception e) {
			}
			
			Logger.print(log);	
		}
	}
	public void setTimeShiftRight(int milliseconds){
		if(gt3xDataRight!=null){
			gt3xDataRight.setShift(gt3xDataRight.getShift()+milliseconds);
			
			updateRight();

			Logger.addEntry("Right GT3X data shifted: "+milliseconds +" ms");
			calcSimilarityRight();
			simView.setGt3xSeries(gt3xLMsRight);
			try {
				simView.calcSimilarity();
			} catch (Exception e) {
			}

			Logger.print(log);	
		}
	}
	
	private void showTitle(){
		String title="";
		if(gt3xFileNameLeft!=null){
			title=title + gt3xFileNameLeft + "(L)" ;
		}
		if(gt3xFileNameRight!=null){
			if(!title.equals("")){
				title=title+" & ";
			}
			title=title + gt3xFileNameRight + "(R)" ;
		}
		if(psgFileName!=null){
			if(!title.equals("")){
				title=title+" & ";
			}
			title=title + psgFileName + "(PSG)" ;
		}
		chartPanel.getChart().setTitle(title);
	}

	private void calcSimilarityLeft(){
		if(gt3xLMsLeft!=null && gt3xPLMsLeft!=null && psgLMs!=null && psgPLMs!=null){
			Logger.addEntry("Left Similarity (LM): "+gt3xLMsLeft.getSimilarity(psgLMs)+"%");
			Logger.addEntry("Left Similarity (PLM): "+gt3xPLMsLeft.getSimilarity(psgPLMs)+"%");
		}
	}
	private void calcSimilarityRight(){
		if(gt3xLMsRight!=null && gt3xPLMsRight!=null && psgLMs!=null && psgPLMs!=null){
			Logger.addEntry("Right Similarity (LM): "+gt3xLMsRight.getSimilarity(psgLMs)+"%");
			Logger.addEntry("Right Similarity (PLM): "+gt3xPLMsRight.getSimilarity(psgPLMs)+"%");
		}
	}

/*	private void openAutodetect(){
		FileFilter filter = new FileNameExtensionFilter("CSV Datei", "csv");
		MovyzerFileChooser c = new MovyzerFileChooser(MovyzerFileChooser.AUTODETECT);
		c.setDialogTitle("Select Sensor file (AUTODETECT)");
		c.addChoosableFileFilter(filter);
		c.setVisible(true);
		fileChooserDialogResult = c.showOpenDialog(null);

		if (fileChooserDialogResult == JFileChooser.APPROVE_OPTION){
			fileChooserChoosenFile = c.getSelectedFile();
			switch (c.getFiletype()){
			case MovyzerFileChooser.GT3X: openGT3XFileLeft(); break;
			case MovyzerFileChooser.PSG: openPSGFile(); break;
			default: JOptionPane.showMessageDialog(this, "There was an error opening this file.", "Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
*/
	private void exportLeft(){
		if(gt3xLMsLeft==null){
			return;
		}
		JFileChooser filechooser=new JFileChooser();
		filechooser.showSaveDialog(this);
		File file=filechooser.getSelectedFile();
		if(file==null){
			return;
		}
		try {
			gt3xLMsLeft.export(file.getPath());
		} catch (Exception e) {
			e.printStackTrace();
			JOptionPane.showMessageDialog(this, "Export failed\n"+e.getMessage());
		}
	}
	private void exportRight(){
		if(gt3xLMsRight==null){
			return;
		}
		JFileChooser filechooser=new JFileChooser();
		filechooser.showSaveDialog(this);
		File file=filechooser.getSelectedFile();
		if(file==null){
			return;
		}
		try {
			gt3xLMsRight.export(file.getPath());
		} catch (Exception e) {
			e.printStackTrace();
			JOptionPane.showMessageDialog(this, "Export failed\n"+e.getMessage());
		}
	}
	private void openSimilarityViewLeft(){
		simView=new SimilarityView(this,gt3xLMsLeft,psgLMs,true);	
	}
	private void openSimilarityViewRight(){
		simView=new SimilarityView(this,gt3xLMsRight,psgLMs,false);	
	}

	private void web(){
		java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
		try {
			java.net.URI uri = new java.net.URI("http://movyzer.googlecode.com");
			desktop.browse(uri);
		}
		catch (Exception e) {
			e.printStackTrace();
		}      
	}

	private void about(){
		JOptionPane.showMessageDialog(this,
				"This is a TUM project.",
				"About Movyzer",
				JOptionPane.PLAIN_MESSAGE);
	}

	public static void main(String[] args) {
		new MovyzerMain(x, y, instance);
	}
}